﻿#region Using

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using XNgine.Input;
using XNgine.Services;

#endregion

namespace XNgine.ScreenManagement.StandardScreens.Menu
{
    public abstract class MenuScreen : GameScreen
    {
        private readonly Vector2 TITLE_ORIGIN = Vector2.Zero;
        /// <summary>  
        /// A default font for menu titles
        /// </summary>  
        public static SpriteFont TitleFont { get; set; }

        /// <summary>
        /// Title of the menu screen
        /// </summary>
        public string Title { get; set; }

        private readonly List<MenuItem> _items = new List<MenuItem>();

        protected List<MenuItem> Items
        {
            get { return _items; }
        }

        private int selectedItem;

        protected MenuScreen(string name)
            : base(name)
        {
            BlocksDraw = true;
            BlocksUpdate = true;
            BlocksInput = true;

            InitializeHandlers();

            InitializeMenuItems();
        }

        protected MenuScreen(string name, string title)
            : this(name)
        {
            Title = title;
        }

        private void InitializeHandlers()
        {
            IKeyboardDevice kbd = XEngine.Instance.GetService<IKeyboardDevice>();
            if (kbd == null)
                throw new Exception("Keyboard device must be registered as a service" +
                                    "in order to use MenuScreen!");
            kbd.KeyPressed += kbd_KeyPressed;
            kbd.KeyHeld += kbd_KeyHeld;
        }

        //private TimeSpan pressed = TimeSpan.Zero;

        private RepeatInterval repeat=new RepeatInterval(TimeSpan.FromSeconds(0.5f));
        private void kbd_KeyHeld(Collection<Keys> keys)
        {
            if (!IsInputAllowed) return;
            if (!repeat.ShouldTriggerKeyHeld()) return;
            
            if (keys.Contains(Keys.Down))
            {
                SelectNext();
            }
            if (keys.Contains(Keys.Up))
            {
                SelectPrevious();
            }
        }

        private void kbd_KeyPressed(Collection<Keys> keys)
        {
            if (!IsInputAllowed) return;
            
            repeat.Trigger();

            if (keys.Contains(Keys.Down))
            {
                SelectNext();
            }
            if (keys.Contains(Keys.Up))
            {
                SelectPrevious();
            }
            if (keys.Contains(Keys.Enter) || keys.Contains(Keys.Space))
            {
                _items[selectedItem].OnActivated();
            }
        }

        public void SelectPrevious()
        {
            selectedItem--;
            if (selectedItem < 0)
                selectedItem = _items.Count - 1;
        }

        public void SelectNext()
        {
            selectedItem++;
            if (selectedItem >= _items.Count)
                selectedItem = 0;
        }

        public override void LoadContent()
        {
            if (ContentLoaded) return;
            if (TitleFont == null)
                TitleFont = XEngine.Instance.Content.Load<SpriteFont>("Fonts/menufont");
            foreach (MenuItem item in _items)
                item.LoadContent();
            ContentLoaded = true;
        }

        public override void UnloadContent()
        {
            foreach (MenuItem item in _items)
                item.UnloadContent();
            ContentLoaded = false;
        }

        protected abstract void InitializeMenuItems();

        public override void Update()
        {
            // Update each nested MenuItem object.  
            for (int i = 0; i < _items.Count; i++)
            {
                bool isSelected = i == selectedItem;
                _items[i].Update(this, isSelected);
            }
        }

        /// <summary>  
        /// Draws the menu.  
        /// </summary>  
        public override void Draw()
        {
            Vector2 position = new Vector2(100, 150);

            XEngine.Instance.SpriteBatch.Begin(SpriteBlendMode.AlphaBlend,
                SpriteSortMode.BackToFront, SaveStateMode.SaveState);

            // Draw each menu entry in turn.  
            for (int i = 0; i < _items.Count; i++)
            {
                MenuItem item = _items[i];

                bool isSelected = i == selectedItem;
                item.Draw(this, position, isSelected);
                position.Y += item.GetHeight(this);
            }

            // Draw the menu title.
            Viewport vp = XEngine.Instance.GraphicsDevice.Viewport;
            Vector2 titlePosition = new Vector2(vp.Width / 3, TitleFont.LineSpacing);
            Vector2 titleOrigin = TitleFont.MeasureString(Title) / 2;
            Color titleColor = Color.White;
            float titleScale = 1.25f;


            XEngine.Instance.SpriteBatch.DrawString(TitleFont, Title, titlePosition, titleColor, 0,
                                                    TITLE_ORIGIN, titleScale, SpriteEffects.None, 0);
            XEngine.Instance.SpriteBatch.End();
        }
    }
}